asynx.namespace("autocomplete");

asynx.autocomplete = function() {
	this._init(arguments);
};

asynx.autocomplete.prototype = {
	
	_init: function(arguments) {
		
		var args = arguments[0];
		
		this.arguments = args;
		
		this.data = args.data;
		
		this.numRows = 0;
		
		this.input = asynx(args.input);
		
		this.container = asynx(args.container);

		this.multipleChoices = args.multiple == false ? false : true;

		this.fastRender = args.fastRender == false ? false : true;

		this.gridLayout = args.gridLayout == false ? false : true;
		
		this.rangeText = args.rangeText == false ? false : true;
		
		this.highlight = args.highlight;
		
		this.datalist = null;
		
		this.selectedItem = null;
		
		this.tbody = null;
		
		this.onStopTyping = null;
		
		this.effects = [];
		
		this.hasFiredEffects = false;
		
		this.canFireEffects = false;
		
		this._createDatalist();
		
		this._initDefaultCss();
		
		this._bindInputEvents();
		
		this._bindRowEvents();
	},
	
	_createDatalist: function() {
		
		this.datalist = new asynx.datalist({
			container: this.container,
			fastRender: this.fastRender,
			gridLayout: this.gridLayout,
			data: this.data
		});
		
		this.addEffect(function() {
			asynx.anim.fade(this, {from:0, to:100, duration:30, equation: 'strongOut'});
			asynx.anim.show(this, {from:0, to:100, duration:30, equation: 'strongOut'}, "y");
		});
		
		this.datalist.hide();
	},
	
	_destroy: function() {
		
		asynx.delay(function() {
			this.numRows = 0;
			this.hide();
			this.selectedItem = null;
		}, 50, false, this);
		
	},
	
	_initDefaultCss: function() {
		
		this.inputHeight = this.input.css("height");
		this.inputWidth = this.input.css("width");
		this.inputTop = this.input.css("top");
		this.inputLeft = this.input.css("left");
		
		var userContainerWidth = this.datalist.containerCss["width"];
		var userContainerHeight = this.datalist.containerCss["height"];
		
		
		this.datalist.setContainerCss({
			position: 'absolute',
			width: userContainerWidth?userContainerWidth:this.inputWidth,
			top: this.inputTop + this.inputHeight,
			left: this.inputLeft
		});
		
		if (userContainerHeight) {
			this.datalist.setContainerCss({
				overflow: 'auto',
				height: userContainerHeight
			});
		}
		
	},
	
	_bindRowEvents: function() {
		var scope = this;
		
		this.datalist.onMouseOver = function(info, e) {
			scope._selectItem(info.tr);
		}
		
		this.datalist.onMouseDown = function(column,a) {
			scope._chooseItem();
		}
	},
	
	_bindInputEvents: function() {
		var scope = this;
		
		asynx.event.add('blur', this.input, function(e,a) {
			scope._destroy();
		});
		
		this.input.keyup(function(e,a) {
			var key = e.keyCode;
			
			if (!scope._isBlockedKey(key)) {
				scope.doQuery(scope.input.value);
			}
			
		});
		
		asynx.event.key(this.input, {type:"keypress", keys:[asynx.event.ENTER]}, function(e, a) {
			
			this._chooseItem();
			this._destroy();
			
		}, null, this);
		
		this.input.whileKeyPressed([asynx.event.DOWN], function(e,a) {
			if (!this.selectedItem) return;
		
			var n = this.selectedItem.nextSibling, f = this.tbody.firstChild;
			scope.selectedItem.css({bg:""});
			this._selectItem(n?n:f);
			
			this._adjustScrollPosition();
			
			if (this.rangeText)
				asynx.selectTextRange(this.input, 0, this.input.value.length);
			
		}, null, null, null, this);
		

		this.input.whileKeyPressed([asynx.event.UP], function(e,a) {
			if (!this.selectedItem) return;
			
			var p = this.selectedItem.previousSibling, l = this.tbody.lastChild;
			scope.selectedItem.css({ bg: "" });
			this._selectItem(p?p:l);	
			
			this._adjustScrollPosition();
			
			if (this.rangeText)
				asynx.selectTextRange(this.input, 0, this.input.value.length);
			
		}, null, null, null, this);
		
		
		asynx.event.onStopTyping(this.input, function(e) {
			if (scope.onStopTyping) scope.onStopTyping.apply(scope, [e]);
		});
		
	},
	
	_adjustScrollPosition: function() {
		if (this.selectedItem) {
			var totalRows = this.numRows;
			var scrollHeight = this.container.scrollHeight;
			var lineHeight = Math.ceil(scrollHeight/totalRows);
			var line = this.selectedItem.getAttribute("dl_row");
			this.container.scrollTop = line * lineHeight;
		}
	},
	
	_setInputText: function(t) {
	
		this.input.value = t;
	
	},
	
	_selectItem: function(item) {
		
		if (this.selectedItem) {
			this.selectedItem.css({bg: ""});
			//log(this.selectedItem)
		}
		this.selectedItem = asynx(item);
		this.selectedItem.css({bg: this.datalist.highlightColor });
		
	},
	
	_chooseItem: function() {
		if (!this.selectedItem)
				return;
				
		var column = this.selectedItem.firstChild;
		
		var info = {
			tr: column,
			innerHTML: column.innerHTML,
			text: column.getAttribute('dl_text'),
			value: column.getAttribute('dl_value')
		};
		
		var v = info.value, t = info.text;
		
		this._setInputText(v?v:t);
		
		if (asynx.isSafari) {
			// safari focus fixed
			asynx.delay(function(){ this.input.focus(); }, 100, false, this);
		}
	},
	
	_isBlockedKey: function(key) {
		
		var keys = asynx.event,
		
			blocked = [
				keys.DOWN, keys.UP, keys.RIGHT, 
				keys.LEFT, keys.ENTER, keys.ESC, 
				keys.CONTROL, keys.SHIFT, keys.F5
				/*,keys.BACKSPACE, keys.DELETE*/
			];
		
		if (asynx.isInArray(key, blocked)) return true;
		else false;
	},
	
	doQuery: function() {
		
		var scope = this, filter = arguments[0], 
			tableGrid = asynx(this.datalist.XPATH_TABLE);
		
		if (filter) {
			
			if (!tableGrid)	this.datalist.create();
			
			this.datalist.doQuery(filter, function() {

				scope.tbody = asynx(scope.datalist.XPATH_TABLE + "//tbody");
				
				
				if (scope.canFireEffects && !scope.hasFiredEffects
						 && scope.effects.length > 0) {
					
					scope.hasFiredEffects = true;
					
					asynx.each(scope.effects, function(effect) {
						effect.apply(scope.container, [scope]);
					});
					
				}else{
					scope.show();
				}
				
				try { scope._selectItem(asynx(scope.tbody.firstChild)); }
				catch(e) {}
				
				scope.numRows = scope.data.DS.numRows;
				
				if (scope.numRows == 0) {
					scope.datalist.hide();
				}
				
			});

		}else{
			scope._destroy();
		}

		this._initDefaultCss();
	},
	
	setHighlightColor: function(color) {
		this.datalist.setHighlightColor(color);
	},
	
	setRowCss: function(css) {
		this.datalist.setRowCss(css);
	},
	
	setColumnCss: function(css) {
		this.datalist.setColumnCss(css);
	},
	
	setIconCss: function(css) {
		this.datalist.setIconCss(css);
	},
	
	setContainerCss: function(css) {
		this.datalist.setContainerCss(css);
	},
	
	setTableCss: function(css) {
		this.datalist.setTableCss(css);
	},
	
	setWidth: function(w) {
		this.datalist.setContainerCss({
			width: w
		});
	},
	
	setHeight: function(h) {
		this.datalist.setContainerCss({
			height: h
		});
	},
	
	show: function() {
		this.datalist.show();
	},
	
	hide: function() {
		this.hasFiredEffects = false;
		this.datalist.hide();
	},
	
	addEffect: function(effect) {
		this.effects.push(effect);
	},
	
	enableEffects: function() {
		this.canFireEffects = true;
	},
	
	disableEffects: function() {
		this.canFireEffects = false;
	}
	
};